#include "Calculator.h"
void IniteStack(pStack* pps)
{
	assert(pps);
	pStack tmp = (pStack)malloc(sizeof(SqStack));
	if (tmp)
	{
        *pps = tmp;
		(*pps)->top = -1;//当只存了一个数据时，它可以用data[0]来访问，此时top应该是0，那么空栈的top自然应该是-1
	}
	else
	{
		perror("malloc");
        exit(1);
	}
}

int StackEmpty(SqStack s)
{
	if (s.top == -1)
		return 1;
	else
		return 0;
}

void Push(pStack ps, int x)
{
	assert(ps->top < MAXSIZE - 1);
	ps->data[++(ps->top)] = x;//先自加top，再存入数据
}

int Pop(pStack ps)
{
	assert(StackEmpty(*ps) == 0);
	ps->top--;
	return ps->data[ps->top + 1];
}

int GetTop(SqStack s)
{
	return s.data[s.top];
}

void Destroy(pStack* pps)
{
	free(*pps);
	*pps = NULL;
}

int getIndex(char theta) //获取 theta 所对应的索引
{
	int index = 0;
	switch (theta)
	{
	case '+':
	index = 0;
	break;
	case '-':
	index = 1;
	break;
	case '*':
	index = 2;
	break;
	case '/':
	index = 3;
	break;
	case '(':
	index = 4;
	break;
	case ')':
	index = 5;
	break;
	case '#':
	index = 6;
	default:break;
	}
	return index;
}

char getPriority(char theta1, char theta2)
{
	const char priority[][7] =
	{
		{ '>', '>', '<', '<', '<', '>', '>' },
		{ '>', '>', '<', '<', '<', '>', '>' },
		{ '>', '>', '>', '>', '<', '>', '>' },
		{ '>', '>', '>', '>', '<', '>', '>' },
		{ '<', '<', '<', '<', '<', '=', '0' },
		{ '>', '>', '>', '>', '0', '>', '>' },
		{ '<', '<', '<', '<', '<', '0', '=' },
	};//其中出现三个0是因为：先读入）后读入（、先读入#后读入）和先读入（后读入#都是错误的表达式
	int index1 = getIndex(theta1);
	int index2 = getIndex(theta2);
	return priority[index1][index2];
}

//弹出两个操作数与一个操作符，进行运算
void Compute(pStack ps_num, pStack ps_operator,char c)
{
	char ope = (char)Pop(ps_operator);
	int num1 = Pop(ps_num);
	int num2 = Pop(ps_num);
	if (ope == '+')
	{
		Push(ps_num, num2 + num1);
	}
	else if (ope == '-')
	{
		Push(ps_num, num2 - num1);
	}
	if (ope == '*')
	{
		Push(ps_num, num2 * num1);
	}
	if (ope == '/')
	{
		Push(ps_num, num2 / num1);
	}
}

void GetOperator(pStack ps_num, pStack ps_operator, char c, char top)
{
	char result = getPriority(top, c);
	assert(result != '0');
	if (result == '<')//加减后接乘除:暂时不算加减,保留乘除
	{
		Push(ps_operator, (int)c);
	}
	else if (result == '=')//在输入左括号和数字后马上又输了个右括号:直接删去
	{
		Pop(ps_operator);
	}
	else if(result == '>')//两种情况：任何运算符后接加减/右括号
	{
		if (c == ')')//任何运算符后接右括号
		{
			while (GetTop(*ps_operator) != '(')//算出括号内的结果.括号内应进行顺序运算的部分在输入时就已经算
			//完了,留下的都是右边的优先级会比左边更高的,随后删去左括号
			{
				Compute(ps_num, ps_operator, c);
			}
			Pop(ps_operator);
		}
		else//后接加减:直接顺序运算
		{
			while (ps_num->top > 0)
			{
				Compute(ps_num, ps_operator, c);
				if (GetTop(*ps_operator) == '(')
				{
					break;//特殊情况:该运算在括号内,不应出括号
				}
			}
			Push(ps_operator, (int)c);
		}
	}
}

void CalculatorInit(pStack* pps_num, pStack* pps_operator)
{
	IniteStack(pps_num);
	IniteStack(pps_operator);
	Push(*pps_operator, (int)'#');
}

int CalculatorWork(pStack ps_num, pStack ps_operator, int* pflag)
{
	char read = '0';
	scanf("%c", &read);
	int flag = 1;
	if (read == '=')
		*pflag = 0;
	else
	{
		while (1)
		{
			if (read >= '0' && read <= '9' && flag == 1)
			{
				Push(ps_num, (int)(read - '0'));
				flag = 0;
			}
			else if (read >= '0' && read <= '9' && flag == 0)
			{
				ps_num->data[ps_num->top] *= 10;
				ps_num->data[ps_num->top] += (int)(read - '0');
			}
			else
			{
				if (read != '=')
					GetOperator(ps_num, ps_operator, read, GetTop(*ps_operator));
				else
					GetOperator(ps_num, ps_operator, '#', GetTop(*ps_operator));
				flag = 1;
			}
            if(read == '=')
                break;
			scanf("%c", &read);
		}
		scanf("%c", &read);//仅用于吸收缓冲区里多余的\n
		return Pop(ps_num);
		*pflag = 1;
	}
}